#!/usr/bin/env python3

#==============================================================================
# Functionality
#==============================================================================
import pdb
import sys
import os
import re

# utility funcs, classes, etc go here.

def asserting(cond):
    if not cond:
        pdb.set_trace()
    assert(cond)

def has_stdin():
    return not sys.stdin.isatty()

def reg(pat, flags=0):
    return re.compile(pat, re.VERBOSE | flags)

#==============================================================================
# Cmdline
#==============================================================================
import argparse

parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 
    description="""
TODO
""")
     
parser.add_argument('-v', '--verbose',
    action="store_true",
    help="verbose output" )
     
parser.add_argument('start', type=float)
parser.add_argument('stop', type=float, nargs='?')
parser.add_argument('step', type=float, nargs='?')
parser.add_argument('format', type=str, nargs='?', default='')
parser.add_argument('-i', '--inclusive', action='store_true')
parser.add_argument('-s', '--sep', '--separator', type=str, default=r'\n')

args = None

#==============================================================================
# Main
#==============================================================================


def is_integer(x):
  #return np.can_cast(x, np.int32)
  return isinstance(x, int)


def is_float(x):
  #return np.can_cast(x, np.float32)
  return isinstance(x, float)


def is_exact(x):
  return is_integer(x) or is_float(x) and x == int(x)


def number(x):
  if isinstance(x, str):
    if re.fullmatch('[-]?[0-9]+', x):
      return int(x)
    else:
      return float(x)
  return x


def run():
    args.sep = args.sep.encode().decode('unicode-escape')
    if args.verbose:
        print(args)
    if args.step is None and args.stop is None:
      args.start, args.stop, args.step = 0, args.start, 1
    elif args.step is None:
      args.step = 1
    args.start = float(args.start)
    args.stop = float(args.stop)
    args.step = float(args.step)
    if is_exact(args.start) and is_exact(args.stop) and is_exact(args.step):
      args.start = int(args.start)
      args.stop = int(args.stop)
      args.step = int(args.step)

    if args.inclusive:
      args.stop += args.step

    c = ''
    while args.start < args.stop if args.step > 0 else args.stop < args.start:
      #sys.stdout.write(c + f"%0{args.width}d" % i)
      print(f"{c}{args.start:{args.format}}", end='')
      args.start += args.step
      c = args.sep
    print('')
    return

    c = ''
    for i in range(args.start, args.stop + (0 if args.exclusive else 1), args.step):
      sys.stdout.write(c + f"%0{args.width}d" % i)
      c = ' '
    print('')

def main():
    try:
        global args
        if not args:
            args, leftovers = parser.parse_known_args()
            args.args = leftovers
        return run()
    except IOError:
        # http://stackoverflow.com/questions/15793886/how-to-avoid-a-broken-pipe-error-when-printing-a-large-amount-of-formatted-data
        try:
            sys.stdout.close()
        except IOError:
            pass
        try:
            sys.stderr.close()
        except IOError:
            pass

if __name__ == "__main__":
    main()

